<template>
  <el-popover
    popper-class="icon-selector-popover"
    ref="popoverRef"
    :width="popoverWidth"
    placement="bottom"
    trigger="click"
    v-bind="$attrs"
    @show="handlePopoverShow"
  >
    <template #reference>
      <el-input ref="inputRef" v-bind="$attrs" v-model="searchValue" @input="handleSearch">
        <template #prepend>
          <base-icon :name="modelValue" />
        </template>
        <template #append>
          <base-icon name="iconfont-general gen-guanbi" @click.stop="handleClearInputValue" />
        </template>
      </el-input>
    </template>
    <template #default>
      <div class="icon-selector-warp-row">
        <el-scrollbar ref="selectorScrollbarRef">
          <el-row v-if="filteredIconList.length > 0">
            <el-col
              :xs="6"
              :sm="4"
              :md="4"
              :lg="4"
              :xl="4"
              v-for="(v, k) in filteredIconList"
              :key="k"
              @click="handleIconClick(v)"
            >
              <div class="icon-selector-warp-item" :class="{ 'icon-selector-active': modelValue === v }">
                <base-icon :name="v" />
              </div>
            </el-col>
          </el-row>
          <el-empty :image-size="90" v-else description="暂无相关图标"></el-empty>
        </el-scrollbar>
      </div>
    </template>
  </el-popover>
</template>

<script setup>
  import { formItemContextKey } from "element-plus";

  const props = defineProps({
    modelValue: {
      type: String,
      default: "",
    },
  });

  const emits = defineEmits(["update:modelValue"]);

  onMounted(() => {
    // 动态加载 阿里图标资源
    loadGetAlicdnIconfont();
    // 设置 popover 宽度
    setPopoverWidth();
  });

  const popoverRef = ref();

  // 用于输入框搜索的 ref
  const searchValue = ref("");
  // 用于过滤的 ref，仅在手动输入时更新
  const searchTerm = ref("");

  // 监听外部 v-model 的变化，同步更新输入框的显示值
  watch(
    () => props.modelValue,
    newValue => {
      searchValue.value = newValue;
    },
    { immediate: true }
  );

  // 图标资源
  const iconList = ref([]);

  // 过滤后的图标资源，依赖 searchTerm
  const filteredIconList = computed(() => {
    if (searchTerm.value && iconList.value.length > 0) {
      return iconList.value.filter(v => v.includes(searchTerm.value));
    }
    return iconList.value;
  });

  // 手动输入时，更新 searchTerm 以触发过滤
  const handleSearch = val => {
    searchTerm.value = val;
  };

  // 滚动组件实例
  const selectorScrollbarRef = ref({});

  // popover 打开时，滚动到选中图标的位置
  const handlePopoverShow = () => {
    nextTick(() => {
      const activeIcon = document.querySelector(".icon-selector-active");
      if (activeIcon && selectorScrollbarRef.value) {
        selectorScrollbarRef.value.scrollTo({ top: activeIcon.offsetTop, behavior: "smooth" });
      }
    });
  };

  // 动态加载 阿里图标资源
  const loadGetAlicdnIconfont = () => {
    nextTick(() => {
      const styles = document.styleSheets;
      let sheetsList = [];
      let sheetsIconList = [];
      for (let i = 0; i < styles.length; i++) {
        if (styles[i].href && styles[i].href.indexOf("at.alicdn.com") > -1) {
          sheetsList.push(styles[i]);
        }
      }
      for (let i = 0; i < sheetsList.length; i++) {
        for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
          if (sheetsList[i].cssRules[j].selectorText && sheetsList[i].cssRules[j].selectorText.indexOf(".gen-") > -1) {
            sheetsIconList.push(
              `iconfont-general ${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/::before/gi, "")}`
            );
          }
        }
      }
      if (sheetsIconList.length > 0) iconList.value = sheetsIconList || [];
      else throw new Error("未获取到阿里图标资源，请刷新重试");
    });
  };

  // 输入框实例
  const inputRef = ref();

  // popover 宽度
  const popoverWidth = ref(0);

  // 设置 popover 宽度
  const setPopoverWidth = () => {
    nextTick(() => {
      popoverWidth.value = inputRef.value.$el.offsetWidth;
    });
  };

  // 注入 el-form-item 上下文
  const formItemContext = inject(formItemContextKey, undefined);

  // 触发 el-form-item 校验
  const triggerValidation = () => {
    if (formItemContext?.validate) {
      formItemContext.validate("change").catch(err => console.warn(err));
    }
  };

  // 选择图标
  const handleIconClick = icon => {
    // 如果当前 modelValue 的值和选中的 icon 值一样，先清空原来的值
    if (props.modelValue === icon) {
      emits("update:modelValue", "");
      nextTick(() => emits("update:modelValue", icon));
    } else {
      emits("update:modelValue", icon);
    }
    triggerValidation();
    popoverRef.value.hide();
  };

  // 清空选中图标
  const handleClearInputValue = () => {
    emits("update:modelValue", "");
    triggerValidation();
  };
</script>
<style lang="scss" scoped>
  :deep(.el-popover) {
    --el-popover-padding: 0px;
  }

  :deep(.el-input-group__prepend),
  :deep(.el-input-group__append) {
    background-color: transparent;
  }

  :deep(.el-input__inner) {
    cursor: pointer;
  }

  .icon-selector-warp-row {
    height: 230px;
    overflow: hidden;

    .el-scrollbar {
      padding-right: 8px;
    }

    .el-scrollbar__bar.is-horizontal {
      display: none;
    }

    .icon-selector-warp-item {
      display: flex;
      justify-content: center;
      align-items: center;
      border: 1px solid var(--el-border-color);
      border-radius: 5px;
      margin: 6px 3px;
      margin-top: 0px;
      height: 30px;
      box-sizing: border-box;

      i {
        font-size: 20px;
        color: var(--el-text-color-regular);
      }

      &:hover {
        cursor: pointer;
        background-color: var(--el-color-primary-light-9);
        border: 1px solid var(--el-color-primary-light-5);

        i {
          color: var(--el-color-primary);
        }
      }
    }

    .icon-selector-active {
      background-color: var(--el-color-primary-light-9);
      border: 1px solid var(--el-color-primary-light-5);

      i {
        color: var(--el-color-primary);
      }
    }
  }
</style>
<style>
  .icon-selector-popover.el-popover {
    padding: 12px 4px 12px 12px;
  }
</style>
